import requests
from bs4 import BeautifulSoup
import csv
import re
import time

# 目标网页URL（豆瓣Top250第一页）
url = "https://movie.douban.com/top250?start=0&filter="

# 模拟真实浏览器的请求头
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
    "Referer": "https://movie.douban.com/",
    "Connection": "keep-alive"
}

try:
    # 模拟人类浏览延迟（2秒）
    time.sleep(2)
    response = requests.get(url, headers=headers)
    response.raise_for_status()  # 捕获HTTP错误（如403、500）
    html = response.text

    # 验证页面是否正常
    if "豆瓣电影 Top 250" not in html:
        print("警告：页面可能被反爬拦截！")
        exit()

    soup = BeautifulSoup(html, "lxml")
    # 关键修复1：正确定位电影列表（<ol class="grid_view">下的所有<li>）
    movie_li_list = soup.find("ol", class_="grid_view").find_all("li")
    if not movie_li_list:
        print("未找到电影列表标签，请检查页面结构！")
        exit()

    result = []
    for index, movie_li in enumerate(movie_li_list, 1):
        try:
            # 1. 提取电影名称（正确层级：li → div.item → div.info → div.hd）
            item_div = movie_li.find("div", class_="item")
            info_div = item_div.find("div", class_="info")
            hd_div = info_div.find("div", class_="hd")

            # 主标题（必存在）和副标题（可选）
            title_tags = hd_div.find_all("span", class_="title")
            main_title = title_tags[0].text.strip() if title_tags else "未知标题"
            # 处理副标题（部分电影无英文标题，用"other"标签获取其他译名）
            sub_title = ""
            other_title_tag = hd_div.find("span", class_="other")
            if other_title_tag:
                sub_title = other_title_tag.text.replace("/", "").strip()
            full_title = f"{main_title} {sub_title}"

            # 2. 提取评分（正确层级：li → div.item → div.info → div.bd → span.rating_num）
            bd_div = info_div.find("div", class_="bd")
            rating_span = bd_div.find("span", class_="rating_num", property="v:average")
            rating = rating_span.text.strip() if rating_span else "暂无评分"

            # 3. 提取导演和主演（正确层级：bd_div下的第一个<p>）
            p_tags = bd_div.find_all("p")  # 获取bd_div下的所有<p>标签（共2个）
            if len(p_tags) < 1:
                director = "未知导演"
                actor = "未知主演"
            else:
                # 清理导演/主演文本中的特殊空格（\xa0）和换行
                director_actor_text = p_tags[0].text.strip()
                director_actor_text = re.sub(r'\xa0+', ' ', director_actor_text)  # 替换全角空格
                director_actor_text = re.sub(r'\n+', ' ', director_actor_text)  # 替换换行

                # 分割导演和主演（格式："导演: XXX   主演: XXX"）
                if "主演:" in director_actor_text:
                    director_part, actor_part = director_actor_text.split("主演:")
                    director = director_part.replace("导演:", "").strip()
                    actor = actor_part.strip()
                else:
                    director = director_actor_text.replace("导演:", "").strip()
                    actor = "未知主演"

            # 4. 提取年份、国家、类型（正确层级：bd_div下的第二个<p>）
            if len(p_tags) < 2:
                year = "未知年份"
                country = "未知国家"
                genre = "未知类型"
            else:
                # 清理文本（格式："1994 / 美国 / 犯罪 剧情"）
                year_country_genre_text = p_tags[1].text.strip()
                year_country_genre_text = re.sub(r'\xa0+', ' ', year_country_genre_text)
                # 按"/"分割，过滤空值
                parts = [part.strip() for part in year_country_genre_text.split("/") if part.strip()]
                year = parts[0] if len(parts) > 0 else "未知年份"
                country = parts[1] if len(parts) > 1 else "未知国家"
                genre = parts[2] if len(parts) > 2 else "未知类型"

            # 存储单部电影数据
            movie_data = {
                "序号": index,
                "电影名称": full_title,
                "评分": rating,
                "导演": director,
                "主演": actor,
                "上映年份": year,
                "国家/地区": country,
                "类型": genre
            }
            result.append(movie_data)
            print(f"成功提取 {index}/25: {full_title} | 评分: {rating}")

        except Exception as e:
            print(f"处理第{index}部电影时出错: {str(e)}")
            continue

    # 保存到CSV文件
    with open("豆瓣电影Top250_第一页_修复版.csv", "w", encoding="utf-8-sig", newline="") as f:
        fieldnames = ["序号", "电影名称", "评分", "导演", "主演", "上映年份", "国家/地区", "类型"]
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(result)

    print(f"\n爬取完成！共提取{len(result)}部电影，文件已保存为：豆瓣电影Top250_第一页_修复版.csv")

except requests.exceptions.RequestException as e:
    print(f"网络请求失败: {str(e)}")
except Exception as e:
    print(f"程序整体错误: {str(e)}")